
#include "ut.h"

#include <ql/alloc.h>
#include <ql/stream.h>

#include <string.h>


static void mem_stream_test()
{
    const char * str = "this is a test";
    char * str2;
    struct QlStream * s;

    QL_UT_BEGIN("mem stream");

    s = ql_create_memory_stream((char **)&str, strlen(str), true, 0, 0);
    QL_UT_VERIFY_CRITICAL(s != NULL);

    str2 = ql_mallocz(strlen(str) + 1);

    for (;;)
    {
        char buffer[3] = { 0 };
        QlStreamInt bytes_read;

        bytes_read = ql_stream_read(s, buffer, 2);
        if (bytes_read == 0)
        {
            break;
        }

        buffer[bytes_read] = 0;
        strcat(str2, buffer);
    }
    
    QL_UT_VERIFY(0 == strcmp(str, str2));

    ql_stream_free(s);
    ql_free(str2);
    QL_UT_END();
}

static void * mem_stream_realloc(void * p, size_t s)
{
    return ql_realloc(p, s);
}

static void mem_stream_free(void * p)
{
    ql_free(p);
}

static void mem_stream_test2()
{
    char * data = NULL;
    struct QlStream * s;
    QlStreamInt pos;
    const char * target_str  = "1str_abcd";
    const char * target_str2 = "1s345abcdefg";

    QL_UT_BEGIN("mem stream test2");

    s = ql_create_memory_stream(&data, 0, false, &mem_stream_realloc, &mem_stream_free);
    QL_UT_VERIFY_CRITICAL(s != NULL);

    QL_UT_VERIFY(ql_stream_putc(s, '1'));
    QL_UT_VERIFY(ql_stream_puts(s, "str"));
    QL_UT_VERIFY(ql_stream_putc(s, '_'));
    QL_UT_VERIFY(ql_stream_putc(s, 'a'));
    QL_UT_VERIFY(3 == ql_stream_write(s, "bcd", 3));

    pos = ql_stream_pos(s);
    QL_UT_VERIFY(pos == strlen(target_str));
    QL_UT_VERIFY(0 == memcmp(target_str, data, pos));

    QL_UT_VERIFY(ql_stream_seek(s, 2));
    QL_UT_VERIFY(ql_stream_puts(s, "345"));
    QL_UT_VERIFY(ql_stream_seek(s, pos));
    QL_UT_VERIFY(ql_stream_putc(s, 'e'));
    QL_UT_VERIFY(ql_stream_puts(s, "fg"));

    pos = ql_stream_pos(s);
    QL_UT_VERIFY(pos == strlen(target_str2));
    QL_UT_VERIFY(0 == memcmp(target_str2, data, pos));

    ql_stream_free(s);
    QL_UT_END();
}

void test_stream()
{
    mem_stream_test();
    mem_stream_test2();
}
